﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace AppServidor
{
  public  class Server
    {



    const int PUERTO=9040;
    Thread hilo;
  public  List<string> bitacora;
  public  List<string> incidentes;
    bool parar = false;
    int cont_mensaje = 0;
    Socket nuevo_socket;
        public Server()
    {
       
            bitacora=new List<string>();
            incidentes = new List<string>();
            hilo = new Thread(new ThreadStart(EsperandoMensajes));
          
           hilo.Name="Servidor para clientes android";
           parar = false;
        }
        public void iniciar(){
            if(!hilo.IsAlive)
               hilo.Start();
        }

        IPEndPoint localEndPoint;
        Socket listener;

        public  void EsperandoMensajes()
        {
      

            // Estable el punto de coneccion
         
            localEndPoint = new IPEndPoint(IPAddress.Any, PUERTO);

            // Create a TCP/IP socket.
            listener = new Socket(AddressFamily.InterNetwork,
                SocketType.Stream, ProtocolType.Tcp);

            // activa el socket que escucha en el puerto especificado
            try
            {
                listener.Bind(localEndPoint);
                listener.Listen(10);

                // Se queda a la espera de nuevas conecciones
                while (!parar)
                {
                    Console.WriteLine("Esperando coneccion...");
                    incidentes.Add("Esperando nueva peticion..." );
                    bitacora.Add("fecha: " + DateTime.Today.ToString());
                    // El hilo se queda suspendido hasta que haya una nueva coneccion
                   nuevo_socket= listener.Accept();
                   Thread nueva_tarea = new Thread(new ThreadStart(ejecucion_peticion));
                   nueva_tarea.Name = "hilo de atencion a clientes";
                   nueva_tarea.Start();
                }

            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }

            Console.WriteLine("\nPress ENTER to continue...");
         

        }
      
        private void ejecucion_peticion() {
            try
            {
                Socket handler = nuevo_socket;
            // iniciamos el buffer, se supone que lo maximo que recibimos es 2kB
            byte[] bytes = new Byte[2 * 1024];
            int bytesRec = handler.Receive(bytes);
            String data = Encoding.ASCII.GetString(bytes, 0, bytesRec);
            incidentes.Add("peticion atendida en la fecha: " + DateTime.Today.ToString());
            // Mensaje en consola
            Console.WriteLine("Mensaje recibido : {0}", data);
            string respuesta = this.procesar_peticion(data);
            bitacora.Add("peticion: \n" + data + "\nrepuesta: \n" + respuesta);
            //le enviamos un mensaje al cliente
            byte[] msg = Encoding.ASCII.GetBytes(respuesta);
            handler.Send(msg);

            handler.Shutdown(SocketShutdown.Both);
            handler.Close();
            }
            catch (Exception e)
            {
                incidentes.Add("X( peticion fallida en fecha: " + DateTime.Today.ToString());
                bitacora.Add(e.ToString());
                Console.WriteLine(e.ToString());
            }
        }

      
       

        public string procesar_peticion(string xml_client) {
         PeticionAndroid p=   ProcesadorXml.procesar_respuesta(xml_client);
         if (p != null) {
             if ("lista".Equals(p.Tipo)) {
                 if (p.Nombre == null)
                 {

                     return this.todas_las_listas();
                 }
                 else {
                     return this.get_lista(p.Nombre);
                 }
             
             }
             if ("pista".Equals(p.Tipo))
             {
                 if (p.Nombre == null)
                 {

                     return this.todas_las_pistas();
                 }
                 else
                 {
                     return this.get_pista(p.Nombre);
                 }

             }
             if ("pistanueva".Equals(p.Tipo))
             {
                 if (p.Pista != null)
                 {
                   bool estado=  p.Pista.guardar(p.Pista.Nombre);
                   if (estado) {
                       return "<correcto>Pista guarda correctamente</correcto>";
                   }
                   return "<error>la pista no pudo ser guarda</error>";
                 }
                

             }
         
         }

         return "<error>el formato del xml no es el correcto</error>";
        }


        public String todas_las_listas() {
            BibliotecaLista.cargar_data_lista();
            List<Lista> listas = BibliotecaLista.bibliotecaListas;
            string xml = "<listas>\n";
            foreach (Lista l in listas) {
                xml += "< lista nombre = \""+l.Nombre+"\" pistas = "+l.SizePista.ToString()+"/>\n";
            }
            xml += "</listas>";
            return xml;
        }


        public String get_lista(string nombre)
        {
            BibliotecaLista.cargar_data_lista();
            List<Lista> listas = BibliotecaLista.bibliotecaListas;
           
            foreach (Lista l in listas)
            {
                if (l.Nombre.Equals(nombre)) {
                    return l.generarXmlCodigo();
                }
            }

            return "<error>la lista pedida no existe</error>";
         
        }



        public String todas_las_pistas()
        {
            BibliotecaLista.cargar_data_lista();
            List<string> pistas = BibliotecaLista.allpistas;
            string xml = "<pistas>\n";
            foreach (string l in pistas)
            {
                Pista p = Pista.abrir(l);
              if(p!=null)
                xml += "<pista nombre = \"" + p.Nombre+ "\" duracion = " + p.Duracionms + "/>\n";
            }
            xml += "</pistas>";
            return xml;
        }


        public String get_pista(string nombre)
        {
            BibliotecaLista.cargar_data_lista();
            List<string> pistas = BibliotecaLista.allpistas;
            foreach (string l in pistas)
            {
                if (l.Equals(nombre)) {
                    Pista p = Pista.abrir(l);
                    if (p != null) {
                        return p.generarXmlCodigo();
                    }
                }
            }
            return "<error>la pista: "+nombre+" no existe</error>";
        }
    }
}
